package exchange

import (
	"fmt"
	"github.com/ngaut/log"
	"time"
	"encoding/json"
	"github.com/garyburd/redigo/redis"
	"global/libs/structs"
	"global/constants"
	"global/core"
	"github.com/gorilla/websocket"
)

type BinanceDepth struct {
	Slug 			string
	Pool 			*redis.Pool
	Symbol 			structs.Symbol
	// Conn 			*websocket.Conn
}

func NewBinanceDepth(slug string, pool *redis.Pool) InterfaceDepth {
	return &BinanceDepth{
		Slug: 		slug,
		Pool: 		pool,
	}
}

func (d *BinanceDepth) HandleResponse(result []byte) error {
	type tmpResponse struct {
		Bids 	[][]interface{}		`json:"bids"`
		Asks 	[][]interface{}		`json:"asks"`
	}

	var response tmpResponse
	err := json.Unmarshal(result, &response)
	if err != nil {
		return err
	}

	var depthData structs.Depth
	for _, v := range response.Bids {

		var v1, v2 string
		if tmpV1, ok := v[0].(string); ok {
			v1 = tmpV1
		}

		if tmpV2, ok := v[1].(string); ok {
			v2 = tmpV2
		}

		bids := []string{v1, v2, ""}
		depthData.Bids = append(depthData.Bids, bids)
	}

	for _, v := range response.Asks {
		var v1, v2 string
		if tmpV1, ok := v[0].(string); ok {
			v1 = tmpV1
		}

		if tmpV2, ok := v[1].(string); ok {
			v2 = tmpV2
		}
		asks := []string{v1, v2, ""}
		depthData.Asks = append(depthData.Asks, asks)
	}

	conn := d.Pool.Get()
	defer conn.Close()

	return core.SaveDepth(conn, d.Slug, d.Symbol, depthData)
}

// 连接
func (d *BinanceDepth) ListenAndAccept(symbol structs.Symbol) error {
	d.Symbol = symbol
	uri := fmt.Sprintf("%s%s@depth20", symbol.From, symbol.To)
	url := fmt.Sprintf("%s/ws/%s", constants.BinanceWebsocketBaseUrl, uri)

	for {
		c, _, err := websocket.DefaultDialer.Dial(url, nil)
		if err != nil {
			log.Errorf("Error: dial binance failed, msg: %s", err.Error())
			time.Sleep(5 * time.Second)
			continue
		}

		for {
			_, message, err := c.ReadMessage()
			if err != nil {
				if websocket.IsUnexpectedCloseError(err) {
					break
				}
				log.Errorf("Error: read message from server failed, msg: %s", err.Error())
				continue
			}

			go func(m []byte) {
				err := d.HandleResponse(m)
				if err != nil {
					log.Errorf("Error: handler response msg failed, %s", err)
				}
			}(message)
		}

		if c != nil {
			c.Close()
		}
	}
}
